#include "../include/Dlt645Frame.h"
#include "../include/dlt645def.h"
#include "../../logger/include/CLogger.h"

CDlt645Frame   CDlt645Frame::mDlt645Frame;

CDlt645Frame::CDlt645Frame()
{
}

CDlt645Frame::~CDlt645Frame()
{
}

CDlt645Frame*  CDlt645Frame::getIntanse()
{
    return &mDlt645Frame;
}

int CDlt645Frame::packet_readingdata_req(uint8_t* pszMeterAddr, uint8_t* pszDataFlag, uint8_t* pFrmData, int& iFrmLen, int iPrefixChNum /* =4 */)
{
    uint8_t szFrmData[64];
    if (packet_readingdata_frmpart(pszMeterAddr, pszDataFlag, 0, NULL, szFrmData, iFrmLen, iPrefixChNum) < 0)
   {
       return -1;
   }

    szFrmData[iFrmLen] = CalcCSVal(szFrmData, iFrmLen);   //CS
    iFrmLen++;

    szFrmData[iFrmLen] = CHR_FRMEND;
    iFrmLen++;

    memcpy(pFrmData, szFrmData, iFrmLen);
   
    return iFrmLen;
}

int CDlt645Frame::packet_readingdata_req(uint8_t* pszMeterAddr, uint8_t* pszDataFlag, uint8_t ucBlockID, uint8_t* pFrmData, int& iFrmLen,
                                            int iPrefixChNum /* = 4 */)
{
    uint8_t szFrmData[64];
    if (packet_readingdata_frmpart(pszMeterAddr, pszDataFlag, ucBlockID, NULL, szFrmData, iFrmLen, iPrefixChNum) < 0)
    {
        return -1;
    }

    szFrmData[iFrmLen] = ucBlockID + FLAG_ERRIDENT;
    ++iFrmLen;
    szFrmData[iFrmLen] = CalcCSVal(szFrmData, iFrmLen);   //CS
    ++iFrmLen;

    szFrmData[iFrmLen] = CHR_FRMEND;
    ++iFrmLen;

    memcpy(pFrmData, szFrmData, iFrmLen);

    return iFrmLen;
}

int CDlt645Frame::packet_readingdata_req(uint8_t* pszMeterAddr, uint8_t* pszDataFlag, uint8_t ucBlockID, uint8_t* pszDateTime, uint8_t* pFrmData,
                                            int& iFrmLen, int iPrefixChNum /* = 4 */)
{
    uint8_t szFrmData[64];
    if (packet_readingdata_frmpart(pszMeterAddr, pszDataFlag, ucBlockID, pszDateTime, szFrmData, iFrmLen, iPrefixChNum) < 0)
    {
        return -1;
    }

    szFrmData[iFrmLen] = ucBlockID + FLAG_ERRIDENT;
    ++iFrmLen;

    ReverseOrderCpy(szFrmData + iFrmLen, pszDateTime, 5,FLAG_ERRIDENT);
    iFrmLen += 5;

    szFrmData[iFrmLen] = CalcCSVal(szFrmData, iFrmLen);   //CS
    ++iFrmLen;

    szFrmData[iFrmLen] = CHR_FRMEND;
    ++iFrmLen;
    memcpy(pFrmData, szFrmData, iFrmLen);

    return iFrmLen;
}

int CDlt645Frame::packet_readingsubseqdata_req(uint8_t* pszMeterAddr, uint8_t* pszDataFlag, uint8_t ucFrmID, uint8_t* pFrmData, int& iFrmLen, int iPrefixChNum /* = 4 */)
{
    uint8_t szFrmData[64];
    if (packet_readingdata_frmpart(pszMeterAddr, pszDataFlag, ucFrmID, NULL, szFrmData, iFrmLen, iPrefixChNum, true) < 0)
    {
        return -1;
    }

    szFrmData[iFrmLen] = ucFrmID + FLAG_ERRIDENT;
    ++iFrmLen;
    szFrmData[iFrmLen] = CalcCSVal(szFrmData, iFrmLen);   //CS
    ++iFrmLen;

    szFrmData[iFrmLen] = CHR_FRMEND;
    ++iFrmLen;

    memcpy(pFrmData, szFrmData, iFrmLen);

    return iFrmLen;
}

int CDlt645Frame::packet_writedata_req(st_dlt645_wrtdata_items stwrtDataitems, uint8_t* pFrmData, int& iFrmLen, int iPrefixChNum /* = 0 */)
{
    unsigned  char szFrmData[64];

    if ((0 > iPrefixChNum) || (4 < iPrefixChNum))
    {
        return -1;
    }

    //前导符
    if (0 < iPrefixChNum)
    {
        memset(szFrmData, CHR_PREFIX, iPrefixChNum);
        iFrmLen += iPrefixChNum;
    }

    //帧起始符
    szFrmData[iFrmLen] = CHR_FRMSTART;
    iFrmLen++;

    //表地址 6字节,由低到高
    ReverseOrderCpy(szFrmData + iFrmLen, stwrtDataitems.szMeterAddr, 6);
    iFrmLen += 6;

    //帧起始符
    szFrmData[iFrmLen] = CHR_FRMSTART;
    iFrmLen++;
    //控制码
    szFrmData[iFrmLen] = stwrtDataitems.ctrlcode;
    iFrmLen++;

    //长度
    szFrmData[iFrmLen] = 4 + stwrtDataitems.datalen;   //DI长度+密码长度+操作者代码长度+数据长度
    if (stwrtDataitems.oprcode_len >0)
    {
        szFrmData[iFrmLen] += stwrtDataitems.oprcode_len;
    }
    if (stwrtDataitems.pwd_len >0)
    {
        szFrmData[iFrmLen] += stwrtDataitems.pwd_len;
    }
    iFrmLen++;

    //数据标识
    ReverseOrderCpy(szFrmData + iFrmLen, stwrtDataitems.szDataFlag, 4, FLAG_ERRIDENT);
    iFrmLen += 4;

    //密码
    if (stwrtDataitems.pwd_len > 0)
    {
        ReverseOrderCpy(szFrmData + iFrmLen, stwrtDataitems.szPasswd, 4, FLAG_ERRIDENT);
        iFrmLen += stwrtDataitems.pwd_len;
    }

    //操作者代码
    if (stwrtDataitems.oprcode_len >0)
    {
        ReverseOrderCpy(szFrmData + iFrmLen, stwrtDataitems.szOprCode, stwrtDataitems.oprcode_len, FLAG_ERRIDENT);
        iFrmLen += stwrtDataitems.oprcode_len;
    }

    //数据
    if (stwrtDataitems.datalen >0)
    {
        ReverseOrderCpy(szFrmData + iFrmLen, stwrtDataitems.frmData, stwrtDataitems.datalen, FLAG_ERRIDENT);
        iFrmLen += stwrtDataitems.datalen;
    }

    szFrmData[iFrmLen] = CalcCSVal(szFrmData, iFrmLen);   //CS
    iFrmLen++;

    szFrmData[iFrmLen] = CHR_FRMEND;
    iFrmLen++;

    memcpy(pFrmData, szFrmData, iFrmLen);
  
    return iFrmLen;
}

int CDlt645Frame::packet_transmit_req(uint8_t* pszMeterAddr, uint8_t* pdata, int datalen, uint8_t* pFrmData, int& iFrmLen, int iPrefixChNum /* = 0 */)
{
    unsigned  char szFrmData[64];

    if ((0 > iPrefixChNum) || (4 < iPrefixChNum))
    {
        return -1;
    }

    //前导符
    if (0 < iPrefixChNum)
    {
        memset(szFrmData, CHR_PREFIX, iPrefixChNum);
        iFrmLen += iPrefixChNum;
    }

    //帧起始符
    szFrmData[iFrmLen] = CHR_FRMSTART;
    iFrmLen++;

    //表地址 6字节,由低到高
    ReverseOrderCpy(szFrmData + iFrmLen, pszMeterAddr, 6);
    iFrmLen += 6;

    //帧起始符
    szFrmData[iFrmLen] = CHR_FRMSTART;
    iFrmLen++;
    //控制码
    szFrmData[iFrmLen] = ENUM_CTRLCODE_TRANSMIT_DATA;
    iFrmLen++;

    //长度
    szFrmData[iFrmLen] =(uint8_t)(1 + datalen);   //转发类型+数据长度
    iFrmLen++;

    szFrmData[iFrmLen] = 0x01; // + FLAG_ERRIDENT;
    iFrmLen++;

    //数据
    if (datalen > 0)
    {
        for (int i = 0; i < datalen; i++)   {
            szFrmData[iFrmLen + i] = pdata[i] + FLAG_ERRIDENT;
        }
        iFrmLen += datalen;
    }

    szFrmData[iFrmLen] = CalcCSVal(szFrmData, iFrmLen);   //CS
    iFrmLen++;

    szFrmData[iFrmLen] = CHR_FRMEND;
    iFrmLen++;

    memcpy(pFrmData, szFrmData, iFrmLen);

    return iFrmLen;
}

int CDlt645Frame::packet_readingdata_frmpart(uint8_t* pszMeterAddr, uint8_t* pszDataFlag, uint8_t ucBlockID, uint8_t* pszDateTime, uint8_t* pFrmData,
                                        int& iFrmLen, int iPrefixChNum, bool bIsSubseq)
{
    int i = 0;
    unsigned  char szFrmData[64];

    if ((0 > iPrefixChNum) || (4 < iPrefixChNum))
    {
        return -1;
    }

    //前导符
    if (0 < iPrefixChNum)
    {
        memset(szFrmData, CHR_PREFIX, iPrefixChNum);
        iFrmLen += iPrefixChNum;
    }

    //帧起始符
    szFrmData[iFrmLen] = CHR_FRMSTART;
    iFrmLen++;

    //表地址 6字节,由低到高
    ReverseOrderCpy(szFrmData + iFrmLen, pszMeterAddr, 6);
    iFrmLen += 6;

    //帧起始符
    szFrmData[iFrmLen] = CHR_FRMSTART;
    iFrmLen++;
    //控制码
    if (!bIsSubseq)
    {
        szFrmData[iFrmLen] = ENUM_CTRLCODE_READ_METERDATA;
    }
    else{
        szFrmData[iFrmLen] = ENUM_CTRLCODE_READ_SUBSEQDATA;
    }
    iFrmLen++;
    //数据域长度
    szFrmData[iFrmLen] = 0x04;	    //帧格式1：数据域只有数据标识，4字节
    if (ucBlockID > 0)
    {
        szFrmData[iFrmLen] ++;      //帧格式2：数据域=据标识+1字节块号，5字节
    }
    if (nullptr != pszDateTime)
    {
        szFrmData[iFrmLen] +=5;     //帧格式3：数据域=数据标识+1字节块号+时间,共10字节;    日期时间为:年月日时分  占5字节
    }
    iFrmLen++;
   

    //数据标识
    for (i = 3; i >= 0; i--)
    {
        szFrmData[iFrmLen] = pszDataFlag[i] + FLAG_ERRIDENT;
        ++iFrmLen;
    }
    memcpy(pFrmData, szFrmData, iFrmLen);

    return iFrmLen;
}

//校验码计算
uint8_t CDlt645Frame::CalcCSVal(uint8_t* pData, int iLen)
{
    unsigned char CS = 0;
    unsigned int uiVal = 0;
    int i = 0;

    for (i = 0; i < iLen; i++)
    {
        uiVal += pData[i];
    }

    CS = uiVal % 256;

    return CS;
}

int CDlt645Frame::ReverseOrderCpy(unsigned char* pDest, unsigned char* pSrc, int iLen, uint8_t errcorr)
{
    int i = 0;
    if (!pDest || !pSrc || (iLen <= 0))
    {
        return 0;
    }

    for (i = 0; i < iLen; i++)
    {
        pDest[i] = pSrc[iLen - i - 1] + errcorr;
    }

    return iLen;
}